#!/usr/bin/env bash

#默认debug不开启
DEBUG=0

#获取指定app名称以及数量
APP_COUNT=$#
(( DEBUG )) && echo "APP_COUNT $APP_COUNT"
WHISKY_ARGS=$*


#设置name变量供其他使用，默认使用该文件名(不带扩展名)
#获取脚本本身名称(通常为whisky),
NAME=$(echo $(basename $0) | sed -e 's/^[SK][0-9]*//' -e 's/\.sh$//')


###################################
#获取脚本所在路径，作为根目录
###################################
SOURCE="$0"
while [ -h "$SOURCE"  ]; do # resolve $SOURCE until the file is no longer a symlink
    DIR="$( cd -P "$( dirname "$SOURCE"  )" && pwd  )"
    SOURCE="$(readlink "$SOURCE")"
    [[ $SOURCE != /*  ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
WHISKY_HOME="$( cd -P "$( dirname "$SOURCE"  )" && pwd  )"

###################################
#检查必要的工作目录是否存在，没有则创建
###################################
WHISKY_RUN="$WHISKY_HOME/.whisky_run"
WHISKY_APP_LIST="$WHISKY_HOME/.whisky_app_list"

if [ -d $WHISKY_RUN ]
then
	(( DEBUG )) && echo ".whisky_run exists."
else
  (( DEBUG )) && echo ".whisky_run not exists,create it."
	mkdir $WHISKY_RUN
fi

if [ -d $WHISKY_APP_LIST ] 
then
  (( DEBUG )) && echo ".whisky_app_list exists."
else
  (( DEBUG )) && echo ".whisky_app_list not exists,create it."
  mkdir $WHISKY_APP_LIST
fi

###################################
#因为shell变量全局，所以读取是先清除上一次读取的配置信息
###################################
clearConfig()
{
  APP_NAME=""
  DESC=""
  JAVA_OPTS=""
  ARGS=""
}

###################################
#读取app根目录下和本脚本名称一样的.conf或.config文件
#配置文件主要包含以下的配置项：
#APP_NAME app的名称
#DESC 该app相关说明
#JAVA_OPTS java虚拟机启动参数
#ARGS app启动时的入参
###################################
readConfig()
{
  clearConfig
  (( DEBUG )) && echo "start read config $1.."
  for CONFIG in $1/${NAME}.conf{,ig}; do
    if [ -f "$CONFIG" ] ; then 
      (( DEBUG )) && echo "find config file $CONFIG"
      source "$CONFIG"
    fi
  done 
  (( DEBUG )) && echo "end read config $1"
}

###################################
#读取目录下的运行jar
#如果有多个jar，以最后一个为准
#不建议同一目录下放多个可运行jar
###################################
readJar()
{
  APP_JAR=""
  (( DEBUG )) && echo "start read jar $1"
  for JAR in $1/*.jar; do
    if [ -f "$JAR" ] ; then 
      APP_JAR="$JAR"
    fi
  done
  (( DEBUG )) && echo "end read jar $1"
}

###################################
#判断 $APP_NAME 是否活动，判断依据为工作目录是否有pid文件
#之所以这么做的原因，是因为希望未来可以支持多实例
###################################
checkAppAlive() {
  if [ -z "$APP_NAME" ]; then
    APP_NAME=$(echo $(basename $1) | sed -e 's/^[SK][0-9]*//' -e 's/\.jar$//')
  fi

  if [ -e "$WHISKY_RUN/${APP_NAME}.pid" ];then
    appid=`cat $WHISKY_RUN/${APP_NAME}.pid`
  else
    appid=0
  fi

  if [ -z "$appid" ]; then
    appid=0
  fi
}

###################################
#初始化，读取脚本所在目录下所有app，记录相关信息。每次添加一个新的app先执行此命令
###################################
init()
{
  (( DEBUG )) && echo "init start================"
  for dir in `ls $WHISKY_HOME`
  do
    if [ -d $dir ];then
      (( DEBUG )) && echo "find dir $dir"
      readJar $dir
      if [ -n "$APP_JAR" ];then
          (( DEBUG )) && echo "find jar $APP_JAR"
          readConfig $dir
          if [ -z "$APP_NAME" ]; then
            APP_NAME=$(echo $(basename $APP_JAR) | sed -e 's/^[SK][0-9]*//' -e 's/\.jar$//')
          fi
          (( DEBUG )) && echo "write info to ${WHISKY_APP_LIST}/${APP_NAME}.info"
          echo $dir > ${WHISKY_APP_LIST}/${APP_NAME}.info
      fi
    fi
  done
  (( DEBUG )) && echo "init end ================"
}

###################################
#输出已有app
###################################
list()
{
  (( DEBUG )) && echo "list start================"
  printf "%-20s\t%-50s\n" "[application]" "[description]"
  for file in `ls ${WHISKY_APP_LIST}/*.info`
  do
    appdir=`cat $file`
    readConfig $appdir
    if [ -z "$APP_NAME" ]; then
      APP_NAME=$(echo $(basename $file) | sed -e 's/^[SK][0-9]*//' -e 's/\.info$//')
    fi
    printf "%-20s\t%-50s\n" "$APP_NAME" "${DESC:-"no description"}" 
  done

  (( DEBUG )) && echo "list end ================"
}

###################################
#启动目标app
###################################
startApp()
{
  (( DEBUG )) && echo "start app, param: ${1}"
  if [ -e "${WHISKY_APP_LIST}/${1}.info" ];then
    appdir=`cat ${WHISKY_APP_LIST}/${1}.info`
    readConfig ${appdir}
    readJar ${appdir}
    checkAppAlive $APP_JAR
    psid=$appid
    printf  "Starting %-40s\t" "$1"
    if [ $psid -ne 0 ]; then
      printf "%20s\t\e[37;43m%2s\e[0m\n\n" "(pid=$psid)" "[started]"
    else
      # start-stop-daemon -S -p"$WHISKY_RUN/${APP_NAME}.pid" -b -m -a "$JAVA_HOME/bin/java $JAVA_OPTS -jar $2 $ARGS >/dev/null 2>&1 &"
      nohup $JAVA_HOME/bin/java $JAVA_OPTS -jar $APP_JAR $ARGS >/dev/null 2>&1 &
      psid=$!
      echo $psid > $WHISKY_RUN/${APP_NAME}.pid
      if [ $psid -ne 0 ]; then
         printf "%20s\t\e[37;42m%s\e[0m\n\n" "(pid=$psid)" "[OK]"
      else
         printf "%20s\t\e[37;41m%s\e[0m\n\n" "" "[Failed]"
      fi
    fi
  else
    echo "can not find app ${1},you may run list command."
  fi
}

###################################
#启动app，不输入app名称则执行全部，可传入多个app
###################################
start()
{
  if [ $APP_COUNT -gt 1 ];then
    i=1
    for arg in $WHISKY_ARGS
    do
      if [ $i == 1 ];then 
        i=2
        continue
      fi
      startApp $arg
    done
  else
    (( DEBUG )) && echo "start all"
    for file in `ls ${WHISKY_APP_LIST}/*.info`
    do
      appdir=`cat $file`
      readConfig $appdir
      if [ -z "$APP_NAME" ]; then
        APP_NAME=$(echo $(basename $file) | sed -e 's/^[SK][0-9]*//' -e 's/\.info$//')
      fi
      startApp $APP_NAME
    done
  fi
}

###################################
#停止目标app
###################################
stopApp()
{
  (( DEBUG )) && echo "stop app, param: ${1}"
  if [ -e "${WHISKY_APP_LIST}/${1}.info" ];then
    appdir=`cat ${WHISKY_APP_LIST}/${1}.info`
    readConfig ${appdir}
    readJar ${appdir}
    checkAppAlive $APP_JAR
    psid=$appid
    printf  "Stoping %-40s\t" "$1"
    if [ $psid -ne 0 ]; then
      
      kill -9 $psid &> /dev/null
      if [ $? -eq 0 ]; then
        printf "%20s\t\e[37;42m%s\e[0m\n\n" "(pid=$psid)" "[OK]"
        rm -f $WHISKY_RUN/${APP_NAME}.pid
      else
        printf "%20s\t\e[37;41m%s\e[0m\n\n" "(pid=$psid)" "[Failed]"
        rm -f $WHISKY_RUN/${APP_NAME}.pid
      fi
    else
      printf "%20s\t\e[37;43m%s\e[0m\n\n" "" "[not run]"
    fi
  else
    echo "can not find app ${1},you may run list command."
  fi
}

###################################
#停止app，不输入app名称则执行全部，可传入多个app
###################################
stop()
{
  if [ $APP_COUNT -gt 1 ];then
    i=1
    for arg in $WHISKY_ARGS
    do
      if [ $i == 1 ];then 
        i=2
        continue
      fi
      stopApp $arg
    done
  else
    (( DEBUG )) && echo "start all"
    for file in `ls ${WHISKY_APP_LIST}/*.info`
    do
      appdir=`cat $file`
      readConfig $appdir
      if [ -z "$APP_NAME" ]; then
        APP_NAME=$(echo $(basename $file) | sed -e 's/^[SK][0-9]*//' -e 's/\.info$//')
      fi
      stopApp $APP_NAME
    done
  fi
}


###################################
#读取脚本的第一个参数($1)，进行判断
#参数取值范围：{start|stop|restart|list|init}
#如参数不在指定范围之内，则打印帮助信息
###################################
case "$1" in
  'start')
    start
    ;;
  'stop')
    stop
    ;;
  'restart')
    stop
    start
    ;;
  'status')
    status
    ;;
  'init')
    init
    ;;
  'list')
    list
    ;;
  *)
     echo "Usage: $0 {start|stop|restart|init|list}"
     exit 1
esac
exit 0